﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using Devtm.Generator.Writers;
using Devtm.Generator.Contexts;
using Devtm.Common;

namespace Devtm.Generator
{


    public class Generator<TWriter, TContext>
        where TWriter : IWriter, new()
        where TContext : IContext, new()
    {

        private TWriter _w;

        public TWriter Writer { get { return _w; } }
        public Project Project { get; private set; }
        public TContext Context { get; private set; }


        public Generator(TContext context)
        {
            // TODO: Complete member initialization
            this.Context = context;
            this.Project = context.DefaultProject;
        }

        public FileInfo NewWriter(string pathNamespace, string filename, string extendName = "", string extension = "")
        {
            this._w = new TWriter();
            this._w.Initialize(Project, extension);
            this._w.File = new FileInfo(this.Project.GetFilename(pathNamespace, filename, extendName) + this._w.Extension);
            this.Log(LogLevelEnm.Trace, "Create file : {0}\\{1}\\", pathNamespace, filename, Tags.Creation);
            return this.Writer.File;
        }

        public bool SaveWriter(string pathNamespace, EnumType contentType = EnumType.NotSpecified)
        {

            if (contentType == EnumType.NotSpecified)
                contentType = this.Writer.ContentType;

            if (this.Writer.Save())
            {
                Project.AddFile(this.Writer.File, contentType, pathNamespace);
                return true;
            }
            else
                Project.RemoveFile(this.Writer.File, contentType, pathNamespace);

            return false;

        }


        #region Import assemblies

        protected void ImportProjectReference(string assemblyName)
        {

            var result = Microsoft.Cci.GlobalAssemblyCache.GetLocation(new System.Reflection.AssemblyName(assemblyName));

            if (result != null)
                Project.ImportAssemblyNameReference(assemblyName);
            else
                throw this.Exception(Strings.TheMethodImportAssemblyException, assemblyName);

        }

        protected void ImportAssemblyNameReference(string assemblyName)
        {

            var result = Microsoft.Cci.GlobalAssemblyCache.GetLocation(new System.Reflection.AssemblyName(assemblyName));

            if (result != null)
                Project.ImportAssemblyNameReference(assemblyName);
            else
                throw this.Exception(Strings.TheMethodImportAssemblyException, assemblyName);

        }

        
        protected void ImportAssemblyReference(System.Reflection.Assembly assembly)
        {

            string n = assembly.GetName().Name;

            if (assembly.GlobalAssemblyCache)
                Project.ImportAssemblyNameReference(n);
            else
            {

                foreach (var item in Project.Solution)
                    if (n == item.AssemblyName)
                    {
                        Project.ImportByProjectReference(item);
                        return;
                    }

                Project.ImportByFilenameReference(n, assembly.Location);

            }
        }

        #endregion



        protected void Log(Devtm.Common.LogLevelEnm level, string log, params object[] parameters)
        {

            var p = parameters.ToList();
            p.Add(Devtm.Common.Tags.BaseTemplateGenerator);
            Devtm.Common.Logger.Log(this, level, log, p);

        }

        protected void Log(Exception exception, params object[] parameters)
        {
            var p = parameters.ToList();
            p.Add(Devtm.Common.Tags.BaseTemplateGenerator);
            Devtm.Common.Logger.Log(this, Devtm.Common.LogLevelEnm.Exception, exception, p);
        }



    }


}
